default:
  interruptible: true

workflow:
  name: $PIPELINE_NAME

include:
  - project: gitlab-org/quality/pipeline-common
    ref: 5.1.1
    file:
      - /ci/base.gitlab-ci.yml
      - /ci/allure-report.yml
      - /ci/knapsack-report.yml

stages:
  - test
  - report
  - notify

# ==========================================
# Templates
# ==========================================
.parallel:
  parallel: 5
  variables:
    QA_KNAPSACK_REPORT_PATH: $CI_PROJECT_DIR/qa/knapsack

.ruby-image:
  # Because this pipeline template can be included directly in other projects,
  # image path and registry needs to be defined explicitly
  image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}:bundler-2.3

.qa-install:
  variables:
    BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES: "true"
    BUNDLE_SILENCE_ROOT_WARNING: "true"
  extends:
    - .gitlab-qa-install

.update-script:
  script:
    - !reference [.bundle-prefix]
    - export QA_COMMAND="$BUNDLE_PREFIX gitlab-qa Test::Omnibus::UpdateFromPrevious $RELEASE $GITLAB_SEMVER_VERSION $UPDATE_TYPE $UPDATE_FROM_EDITION -- $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS"
    - echo "Running - '$QA_COMMAND'"
    - eval "$QA_COMMAND"

.qa:
  extends:
    - .qa-base
    - .qa-install
    - .gitlab-qa-report
  stage: test
  tags:
    - e2e
  variables:
    QA_GENERATE_ALLURE_REPORT: "true"
    QA_CAN_TEST_PRAEFECT: "false"
    QA_INTERCEPT_REQUESTS: "true"
    GITLAB_LICENSE_MODE: test
    GITLAB_QA_ADMIN_ACCESS_TOKEN: $QA_ADMIN_ACCESS_TOKEN
    GITLAB_QA_OPTS: $EXTRA_GITLAB_QA_OPTS
    # todo: remove in 16.1 milestone when not needed for backwards compatibility anymore
    EE_LICENSE: $QA_EE_LICENSE
    GITHUB_ACCESS_TOKEN: $QA_GITHUB_ACCESS_TOKEN
  # Allow QA jobs to fail as they are flaky. The top level `package-and-e2e:ee`
  # pipeline is not allowed to fail, so without allowing QA to fail, we will be
  # blocking merges due to flaky tests.
  allow_failure: true

.trigger-omnibus-env:
  stage: .pre
  needs:
    # We need this job because we need its `cached-assets-hash.txt` artifact, so that we can pass the assets image tag to the downstream omnibus-gitlab pipeline.
    - pipeline: $PARENT_PIPELINE_ID
      job: build-assets-image
  variables:
    BUILD_ENV: build.env
  before_script:
    - |
      # This is duplicating the function from `scripts/utils.sh` since `.gitlab/ci/package-and-test/main.gitlab-ci.yml` can be included in other projects.
      function assets_image_tag() {
        local cache_assets_hash_file="cached-assets-hash.txt"

        if [[ -n "${CI_COMMIT_TAG}" ]]; then
          echo -n "${CI_COMMIT_REF_NAME}"
        elif [[ -f "${cache_assets_hash_file}" ]]; then
          echo -n "assets-hash-$(cat ${cache_assets_hash_file} | cut -c1-10)"
        else
          echo -n "${CI_COMMIT_SHA}"
        fi
      }
  script:
    - |
      SECURITY_SOURCES=$([[ ! "$CI_PROJECT_NAMESPACE" =~ ^gitlab-org\/security ]] || echo "true")
      echo "SECURITY_SOURCES=${SECURITY_SOURCES:-false}" > $BUILD_ENV
      echo "OMNIBUS_GITLAB_CACHE_UPDATE=${OMNIBUS_GITLAB_CACHE_UPDATE:-false}" >> $BUILD_ENV
      for version_file in *_VERSION; do echo "$version_file=$(cat $version_file)" >> $BUILD_ENV; done
      echo "OMNIBUS_GITLAB_RUBY3_BUILD=${OMNIBUS_GITLAB_RUBY3_BUILD:-false}" >> $BUILD_ENV
      echo "OMNIBUS_GITLAB_RUBY2_BUILD=${OMNIBUS_GITLAB_RUBY2_BUILD:-false}" >> $BUILD_ENV
      echo "OMNIBUS_GITLAB_CACHE_EDITION=${OMNIBUS_GITLAB_CACHE_EDITION:-GITLAB}" >> $BUILD_ENV
      echo "OMNIBUS_GITLAB_BUILD_ON_ALL_OS=${OMNIBUS_GITLAB_BUILD_ON_ALL_OS:-false}" >> $BUILD_ENV
      echo "GITLAB_ASSETS_TAG=$(assets_image_tag)" >> $BUILD_ENV
      echo "EE=$([[ $FOSS_ONLY == '1' ]] && echo 'false' || echo 'true')" >> $BUILD_ENV
      target_branch_name="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_COMMIT_REF_NAME}}"
      echo "TRIGGER_BRANCH=$([[ "${target_branch_name}" =~ ^[0-9-]+-stable(-ee)?$ ]] && echo ${target_branch_name%-ee} || echo 'master')" >> $BUILD_ENV
    - |
      echo "Built environment file for omnibus build:"
      cat $BUILD_ENV
  artifacts:
    expire_in: 3 days
    reports:
      dotenv: $BUILD_ENV
    paths:
      - $BUILD_ENV

.trigger-omnibus-env-ce:
  extends: .trigger-omnibus-env
  needs:
    - pipeline: $PARENT_PIPELINE_ID
      job: build-assets-image as-if-foss

.trigger-omnibus:
  stage: .pre
  inherit:
    variables: false
  variables:
    GITALY_SERVER_VERSION: $GITALY_SERVER_VERSION
    GITLAB_ELASTICSEARCH_INDEXER_VERSION: $GITLAB_ELASTICSEARCH_INDEXER_VERSION
    GITLAB_KAS_VERSION: $GITLAB_KAS_VERSION
    GITLAB_METRICS_EXPORTER_VERSION: $GITLAB_METRICS_EXPORTER_VERSION
    GITLAB_PAGES_VERSION: $GITLAB_PAGES_VERSION
    GITLAB_SHELL_VERSION: $GITLAB_SHELL_VERSION
    GITLAB_WORKHORSE_VERSION: $GITLAB_WORKHORSE_VERSION
    GITLAB_VERSION: $CI_COMMIT_SHA
    GITLAB_ASSETS_TAG: $GITLAB_ASSETS_TAG
    IMAGE_TAG: $CI_COMMIT_SHA
    TOP_UPSTREAM_SOURCE_PROJECT: $CI_PROJECT_PATH
    SECURITY_SOURCES: $SECURITY_SOURCES
    CACHE_UPDATE: $OMNIBUS_GITLAB_CACHE_UPDATE
    RUBY3_BUILD: $OMNIBUS_GITLAB_RUBY3_BUILD
    RUBY2_BUILD: $OMNIBUS_GITLAB_RUBY2_BUILD
    CACHE_EDITION: $OMNIBUS_GITLAB_CACHE_EDITION
    BUILD_ON_ALL_OS: $OMNIBUS_GITLAB_BUILD_ON_ALL_OS
    SKIP_QA_TEST: "true"
    ee: $EE
  trigger:
    project: gitlab-org/build/omnibus-gitlab-mirror
    branch: $TRIGGER_BRANCH
    strategy: depend

.trigger-omnibus-ce:
  extends:
    - .trigger-omnibus
  variables:
    # Override gitlab repository so that omnibus doesn't use foss repository for CE build
    GITLAB_ALTERNATIVE_REPO: $CI_PROJECT_URL

.download-knapsack-report:
  extends:
    - .gitlab-qa-image
  stage: .pre
  variables:
    KNAPSACK_DIR: ${CI_PROJECT_DIR}/qa/knapsack
    GIT_STRATEGY: none
  script:
    # when using qa-image, code runs in /home/gitlab/qa folder
    - bundle exec rake "knapsack:download[test]"
    - mkdir -p "$KNAPSACK_DIR" && cp knapsack/*.json "${KNAPSACK_DIR}/"
  allow_failure: true
  artifacts:
    paths:
      - qa/knapsack/*.json
    expire_in: 1 day

.e2e-test-report:
  extends:
    - .generate-allure-report-base
  stage: report
  variables:
    GITLAB_AUTH_TOKEN: $PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE
    ALLURE_PROJECT_PATH: $CI_PROJECT_PATH
    ALLURE_MERGE_REQUEST_IID: $CI_MERGE_REQUEST_IID

.upload-knapsack-report:
  extends:
    - .generate-knapsack-report-base
    - .qa-install
    - .ruby-image
  stage: report
  when: always

.export-test-metrics:
  extends:
    - .qa-install
    - .ruby-image
  stage: report
  when: always
  variables:
    QA_METRICS_REPORT_FILE_PATTERN: $CI_PROJECT_DIR/gitlab-qa-run-*/**/test-metrics-*.json
  script:
    - bundle exec rake "ci:export_test_metrics[$QA_METRICS_REPORT_FILE_PATTERN]"

.relate-test-failures:
  extends:
    - .qa-install
    - .ruby-image
  stage: report
  when: always
  variables:
    QA_RSPEC_JSON_FILE_PATTERN: "${CI_PROJECT_DIR}/gitlab-qa-run-*/**/rspec-*.json"
  script:
    - |
      if [ "$SUITE_FAILED" != "true" ] && [ "$SUITE_RAN" == "true" ]; then
        echo "Test suite passed. Exiting..."
        exit 0
      fi
    - |
      bundle exec relate-failure-issue \
        --input-files "${QA_RSPEC_JSON_FILE_PATTERN}" \
        --project "gitlab-org/gitlab" \
        --token "${QA_RELATE_FAILURE_ISSUE_TOKEN}"

.generate-test-session:
  extends:
    - .qa-install
    - .ruby-image
  stage: report
  when: always
  variables:
    QA_RSPEC_JSON_FILE_PATTERN: "${CI_PROJECT_DIR}/gitlab-qa-run-*/**/rspec-*.json"
  script:
    - |
      bundle exec generate-test-session \
        --input-files "${QA_RSPEC_JSON_FILE_PATTERN}" \
        --project "gitlab-org/quality/testcase-sessions" \
        --token "${QA_TEST_SESSION_TOKEN}" \
        --ci-project-token "${GENERATE_TEST_SESSION_READ_API_REPORTER_TOKEN}" \
        --issue-url-file report_issue_url.txt
  artifacts:
    when: always
    expire_in: 1d
    paths:
      - qa/report_issue_url.txt

.notify-slack:
  extends:
    - .notify-slack-qa
    - .qa-install
    - .ruby-image
  stage: notify
  variables:
    QA_RSPEC_XML_FILE_PATTERN: "${CI_PROJECT_DIR}/gitlab-qa-run-*/**/rspec-*.xml"
    SLACK_ICON_EMOJI: ci_failing
    STATUS_SYM: ☠️
    STATUS: failed
    TYPE: "($QA_RUN_TYPE) "
  when: always
  script:
    - |
      if [ "$SUITE_FAILED" != "true" ] && [ "$SUITE_RAN" == "true" ]; then
        echo "Test suite passed. Exiting..."
        exit 0
      fi
    - bundle exec prepare-stage-reports --input-files "${QA_RSPEC_XML_FILE_PATTERN}"
    - !reference [.notify-slack-qa, script]

# ==========================================
# Pre stage
# ==========================================
dont-interrupt-me:
  stage: .pre
  interruptible: false
  script:
    - echo "This jobs makes sure this pipeline won't be interrupted! See https://docs.gitlab.com/ee/ci/yaml/#interruptible."
  rules:
    - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_MERGE_REQUEST_IID == null'
      allow_failure: true
    - if: '$CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached"'
      when: manual
      allow_failure: true
